<?php
namespace app\api\controller;

class Report extends Permission
{
    public function getProfit()
    {
        // =========================
        // # 前端传入的条件
        // =========================
        $reportAreaId = $this->post('area_id') != '' ?  $this->post('area_id') : 0;
        $reportCompanyId = $this->post('company_id') != '' ?  $this->post('company_id') : 0;

        // =========================
        // # 计算提交上来的时间范围
        // =========================
        $ym        = trim($this->post('belongs_month'));
        $startDate = strtotime($ym . '-01 00:00:00');
        if ($startDate === false) $this->resErr('报表月份有误');
        $endDate   = strtotime('+1 month', $startDate);

        // =============================================
        // # 计算时间范围内的车辆收支数据，毛利，毛利占比
        // =============================================
        $data = $this->_calcProfit($reportAreaId, $reportCompanyId, $startDate, $endDate); 
        // 总毛利
        $totalProfit = $data['totalProfit']; 
        // 区域毛利
        $areaProfit = $data['areaProfit'];        
        // 车队毛利
        $companyProfit = $data['companyProfit'];  
        // 总收入
        $totalIncome = $data['totalIncome']; 
        // 区域收入
        $areaIncome = $data['areaIncome'];        
        // 车队收入
        $companyIncome = $data['companyIncome']; 


        // 含补差价的毛利占比计算方法
        $percenData = $this->_calcProfitRatio($startDate, $endDate, $reportAreaId); 
        // 当前区域毛利占比
        $areaSharePercentage = $reportAreaId > 0 ? $percenData['areaData'][$reportAreaId]['percen'] : 0;
        // 当前车队毛利占比
        $companySharePercentage = $reportCompanyId > 0 ? $percenData['companyData'][$reportCompanyId]['percen'] : 0;

        # 组装报表里面要返回的总收入总支出车辆毛利（看当前是什么报表，返回对应的数组）
        $vehicleData = $this->_setVehicleData($data,$reportAreaId,$reportCompanyId);

        // ==================================================================
        // # 获取车辆收支表的数据和分类,把数据按照分类汇总，分配到分类里面，不在分类里面的，按其他计算
        // ==================================================================

        
        # 获取符合条件（要查看的报表条件）的车辆收支列表
        $vehicleCateData = $this->_calcVehicleCateData($reportAreaId,$reportCompanyId,$startDate,$endDate);


        // ==================================================================
        // # 获取公司费用收支表的数据和分类,把数据按照分类汇总，并计算分摊，分配到分类里面
        // ==================================================================

        # 分类表
        $companyIECate = $this->_getCompanyIncomeExpenseCateTreeList();
        # 费用数据
        $companyCateData = $this->_calcCompanyCateData($companyIECate,$reportAreaId,$reportCompanyId,$startDate,$endDate,$percenData);

        # 单独获取毛利和管理费用综合
        [$vehicleProfit, $manageFee] = $this->_getVehicleProfitAndManageFee($data,$companyCateData,$reportAreaId,$reportCompanyId);

        # 利润
        $profitData = $this->_calcActualProfit($vehicleProfit,$manageFee);

        # 账单
        $billData = $this->_getBillAmount($reportAreaId,$reportCompanyId);

        # 管理成本占车辆毛利比例
        $manageCostRate = $this->_calcManageCostRate($vehicleProfit,$manageFee);
        

        # 拼装要返回的利润列表数据
        $reportList = [];
        $reportList = array_merge($vehicleData, $vehicleCateData);
        $reportList = array_merge($reportList, $companyCateData);
        $reportList = array_merge($reportList, $profitData);
        $reportList = array_merge($reportList, $billData);
        $reportList = array_merge($reportList, $manageCostRate);


        # 最后返回的数据
        $res = [
            'totalProfit' => formatMoneyShow($totalProfit), // 总毛利，用来算数的
            'areaProfit' => $reportAreaId > 0 ? formatMoneyShow($areaProfit) : 0, // 区域毛利，用来看的
            'companyProfit' => $reportCompanyId > 0 ? formatMoneyShow($companyProfit) : 0, // 车队毛利，用来看的
            'areaSharePercentage' => bcmul($areaSharePercentage,100,2),
            'companySharePercentage' => bcmul($companySharePercentage,100,2),
            'reportList' => $reportList,
            'percenData' => $percenData
        ];
        $this->resSuc($res);
    }

    // 从数据里面读取车辆毛利和管理费用总和
    private function _getVehicleProfitAndManageFee($data,$companyCateData,$reportAreaId,$reportCompanyId)
    {
        // 把数字转成分来计算
        // 车辆毛利
        $vehicleProfit = 0;
        if($reportCompanyId > 0)
        {
            $vehicleProfit = $data['companyProfit'];
        }
        elseif($reportAreaId > 0)
        {
            $vehicleProfit = $data['areaProfit'];
        }
        else
        {
            $vehicleProfit = $data['totalProfit'];
        }

        // 管理费用
        $manageFee = 0;
        foreach ($companyCateData as $v) {
            if($v['pid'] == 0) $manageFee += formatMoneySave($v['amount']);
        }
        
        return [$vehicleProfit,$manageFee];
    }
    // 计算纯利润
    private function _calcActualProfit($vehicleProfit,$manageFee)
    {
        $profit = bcsub($vehicleProfit, $manageFee, 0);

        $res = [[
            'backgroundClass' => 'success-row',
            'hasDetail' => 0,
            'cate_id' => 0,
            'type' => '净利润',
            'title' => '三、净利润/利润总额',
            'amount' => formatMoneyShow($profit)
        ]];
        return $res;
    }
    // 账单金额
    private function _getBillAmount($reportAreaId,$reportCompanyId)
    {
        $map = [];
        if($reportAreaId > 0) $map['area_id'] = $reportAreaId;
        if($reportCompanyId > 0) $map['company_id'] = $reportCompanyId;
        $bill = db('Bill')->where($map)->field('SUM(amount + interest - repay_amount - repay_interest) as total')->find();


        $res = [[
            'backgroundClass' => 'warning-row',
            'hasDetail' => 0,
            'cate_id' => 0,
            'type' => '应收账款',
            'title' => '四、应收账款',
            'amount' => formatMoneyShow($bill['total'])
        ]];
        return $res;
    }
    // 计算管理成本占车辆毛利比例
    private function _calcManageCostRate(int $vehicleProfit, int $manageFee)
    {
        // 避免除以0
        if ($vehicleProfit <= 0) {
            $rate = '0.00%';
        } else {
            // (管理费 ÷ 毛利) * 100，保留两位小数
            $rate = bcdiv($manageFee * 100, $vehicleProfit, 2) . '%';
        }

        $res = [[
            'backgroundClass' => 'success-row',
            'hasDetail' => 0,
            'cate_id'   => 0,
            'type'      => '管理成本占比',
            'title'     => '五、管理成本占车辆毛利的比例',
            'amount'    => $rate
        ]];
        return $res;
    }


    private function _setVehicleData($data,$reportAreaId,$reportCompanyId)
    {
        $incomeAmount = $expenseAmount = $profitAmount = 0;
        if($reportCompanyId > 0)
        {
            $incomeAmount = $data['companyIncome'];
            $expenseAmount = $data['companyExpense'];
            $profitAmount = $data['companyProfit'];
        }
        elseif($reportAreaId > 0)
        {
            $incomeAmount = $data['areaIncome'];
            $expenseAmount = $data['areaExpense'];
            $profitAmount = $data['areaProfit'];
        }
        else
        {
            $incomeAmount = $data['totalIncome'];
            $expenseAmount = $data['totalExpense'];
            $profitAmount = $data['totalProfit'];
        }

        $vehicleData = [
            [
                'backgroundClass' => 'success-row',
                'hasDetail' => 1,
                'cate_id' => 0,
                'type' => '车辆总收费',
                'title' => '一、车辆总收费',
                'amount' => formatMoneyShow($incomeAmount)
            ],
            [
                'backgroundClass' => 'warning-row',
                'hasDetail' => 1,
                'cate_id' => 0,
                'type' => '车辆支出',
                'title' => '车辆支出',
                'amount' => formatMoneyShow($expenseAmount)
            ],
            [
                'backgroundClass' => 'success-row',
                'hasDetail' => 1,
                'cate_id' => 0,
                'type' => '总毛利',
                'title' => '二、车辆毛利',
                'amount' => formatMoneyShow($profitAmount)
            ],
        ];

        return $vehicleData;
    }

    private function _calcVehicleCateData($reportAreaId,$reportCompanyId,$startDate,$endDate)
    {
        #获取车辆的收支分类列表
        $cates = db('VehicleIncomeExpenseCate')->order('sort ASC')->select();
        # 获取符合条件的数据
        $map = [
            'belongs_date' => ['BETWEEN',[$startDate,$endDate]],
            'a.status' => 20, // 已审核的
            'is_void' => 1 // 有效的
        ];
        if($reportAreaId > 0) $map['area_id'] = $reportAreaId;
        if($reportCompanyId > 0) $map['company_id'] = $reportCompanyId;

        $rows = db('VehicleIncomeExpense')->alias('a')->join('vehicle b','a.vehicle_id = b.id','LEFT')->where($map)->select();

        # 组装分类初始数组
        $cateData = [];
        foreach ($cates as $cate) {
            $row = [
                'backgroundClass' => 'normal-row',
                'hasDetail' => 1,
                'cate_id' => $cate['id'],
                'type' => '车辆收支',
                'title' => $cate['title'],
                'amount' => 0
            ];
            $cateData[$cate['id']] = $row;
        }

        # 遍历数据，计算每一项分类的毛利
        foreach ($rows as $v) {
            $cateData[$v['cate_id']]['amount'] += $v['io_type'] == '收入' ? $v['amount'] : $v['amount'] * -1;
        }
        foreach ($cateData as $k => $v) {
            $cateData[$k]['amount'] = formatMoneyShow($v['amount']);
        }
        return $cateData;
    }


    /**
     * 动态计算每一条费用，每个区域，每个车队承担多少
     * */
    private function _calcCompanyIncomeExpense($startDate,$endDate,$percenData)
    {
        # 获取符合条件的数据
        $map = [
            'belongs_date' => ['BETWEEN',[$startDate,$endDate]], // 指定的报表月份
            'status' => 200, // 已审核的
        ];
        $rows = db('CompanyIncomeExpense')->where($map)->select();
    }   


    /**
     * @param $cate 组装好的分类的列表
     * @param $reportAreaId 要查的区域ID
     * @param $reportCompanyId 要查的车队ID
     * @param $startDate 开始时间（根据查看的报表月份条件算出来起始时间）
     * @param $endDate 结束时间（根据查看的报表月份条件算出来起始时间）
     * @param $areaSharePercentage 区域毛利占比
     * @param $companySharePercentage 公司毛利占比
     * */
    private function _calcCompanyCateData($cates,$reportAreaId,$reportCompanyId,$startDate,$endDate,$percenData)
    {
        # 获取符合条件的数据
        $map = [
            'belongs_date' => ['BETWEEN',[$startDate,$endDate]], // 指定的报表月份
            'status' => 200, // 已审核的
        ];
        $rows = db('CompanyIncomeExpense')->where($map)->select();

        # 查当前公司所属的区域
        $companyAreaId = 0;
        if($reportCompanyId > 0)
        {
            $company = db('Company')->where('id',$reportCompanyId)->find();
            $companyAreaId = $company['area_id'];
        }

        # 初始化报表数组
        $reportData = $this->_initCateData($rows,$cates,$reportAreaId,$reportCompanyId);

        # 计算总报表
        $reportData = $this->_calcReportData('总报表',$rows,$reportData,$reportAreaId, $reportCompanyId);

        $resultData = $reportData['all'];

        # 计算区域报表
        if($reportAreaId > 0)
        {
            $reportData = $this->_calcReportData('区域报表',$rows,$reportData,$reportAreaId, $reportCompanyId,$percenData);
            $resultData = $reportData['area'][$reportAreaId];
        }

        # 计算车队报表
        if($reportCompanyId > 0)
        {
            $reportData = $this->_calcReportData('车队报表',$rows,$reportData,$reportAreaId, $reportCompanyId,$percenData);
            $resultData = $reportData['company'][$reportCompanyId];
        }

        foreach ($resultData as $key => $value) {
            $resultData[$key]['amount'] = formatMoneyShow($value['amount']);
        }

        foreach ($resultData as $id => &$row) {
            if ($row['pid'] == 0) {
                $sum = "0.00";
                foreach ($resultData as $cid => $child) {
                    if ($child['pid'] == $row['cate_id']) {
                        $sum = bcadd($sum, $child['amount'], 2);
                    }
                }
                $row['amount'] = $sum;
            }
        }
        unset($row); // 断开引用
    
        return $resultData;
    }

    /**
     * 初始化报表数据数组
     * 根据每一条收支去初始化
     * */
    private function _initCateData($rows,$cates,$reportAreaId,$reportCompanyId)
    {
        $reportData = [];
        $areas = [];
        if($reportAreaId > 0)
        {
            $areas = db('CompanyArea')->order('id ASC')->select();
        }

        $companys = [];
        if($reportCompanyId > 0)
        {
            $companys = db('Company')->order('id ASC')->where('area_id',$reportAreaId)->select();
        }
        foreach ($cates as $cate) {
            $row = [
                'backgroundClass' => $cate['pid'] == 0 ? 'warning-row' : 'normal-row',
                'hasDetail' => 1,
                'pid' => $cate['pid'],
                'cate_id' => $cate['id'],
                'type' => '公司费用',
                'title' => $cate['pid'] == 0 ? '减：'.$cate['title'] : $cate['title'],
                'amount' => 0
            ];
            $reportData['all'][$cate['id']] = $row;
            // 区域
            foreach ($areas as $area) {
                $reportData['area'][$area['id']][$cate['id']] = $row;
            }
            // 车队
            foreach ($companys as $company) {
                $reportData['company'][$company['id']][$cate['id']] = $row;
            }
        }

        return $reportData;
    }

    private function _calcReportData($type,$rows,$reportData,$reportAreaId, $reportCompanyId,$percenData = [])
    {
        if($type == '总报表')
        {
            foreach ($rows as $v) {
                $reportData['all'][$v['cate_id']]['amount'] += $v['io_type'] == '支出' ? $v['amount'] : $v['amount'] * -1;
            }
        }

        if($type == '区域报表')
        {
            foreach ($rows as $v) {
                if($v['belongs'] == '区域')
                {
                    # 先算自己区域承担的费用
                    $reportData['area'][$v['area_id']][$v['cate_id']]['amount'] += $v['io_type'] == '支出' ? $v['amount'] : $v['amount'] * -1;
                }
                if($v['belongs'] == '总部')
                {
                    $amount = $v['io_type'] == '支出' ? $v['amount'] : $v['amount'] * -1;
                    # 计算分摊费用并补齐
                    $reportData = $this->_calcShareCost('计算区域分摊',$amount,$v['cate_id'],$reportData,$percenData);
                }
            }
            
        }
        if($type == '车队报表')
        {
            foreach ($rows as $v) {
                if($v['belongs'] == '总部')
                {
                    $amount = $v['io_type'] == '支出' ? $v['amount'] : $v['amount'] * -1;
                    # 计算分摊费用并补齐
                    $reportData = $this->_calcShareCost('计算车队分摊区域承担的费用',$amount,$v['cate_id'],$reportData,$percenData,$reportAreaId);
                }
                else
                {
                    if($reportAreaId != $v['area_id']) continue; // 区域的费用，不是本区域的，就不承担了。
                    if($v['company_id'] > 0)
                    {
                        # 先算自己车队完全承担的费用
                        $reportData['company'][$v['company_id']][$v['cate_id']]['amount'] += $v['io_type'] == '支出' ? $v['amount'] : $v['amount'] * -1;
                    }
                    else
                    {
                        // 算车队承担的费用
                        $amount = $v['io_type'] == '支出' ? $v['amount'] : $v['amount'] * -1;
                        # 计算分摊费用并补齐
                        $reportData = $this->_calcShareCost('计算车队分摊区域的费用',$amount,$v['cate_id'],$reportData,$percenData);
                    }

                }
                
            }
            
        }
        return $reportData;
    }

    // 计算承担的成本
    // $type = 要分摊的费用
    // $amount = 要计算的费用
    // $cateId = 该费用所属的分类
    // $reportAreaId = 当前查看的报表所属的区域，用来获取车队所在区域
    // $reportData = 报表数组
    // $percenData = 毛利率数组
    private function _calcShareCost($type,$amount,$cateId,$reportData,$percenData,$reportAreaId = 0)
    {
        if($type == '计算区域分摊')
        {
            $totalShareAmount = 0;
            foreach ($reportData['area'] as $areaId => $data) {
                $thisAreaProfitPercen = $percenData['areaData'][$areaId]['percen'];
                $thisAreaShareAmount = bcmul($amount,$thisAreaProfitPercen);
                $totalShareAmount += $thisAreaShareAmount;
                $reportData['area'][$areaId][$cateId]['amount'] += $thisAreaShareAmount;
            }
            $diffAmount = $amount - $totalShareAmount;
            # 差价由毛利最高的区域承担
            $maxKey = $this->_getMaxPercenKey($percenData['areaData']);
            $reportData['area'][$maxKey][$cateId]['amount'] += $diffAmount;
        }
        if($type == '计算车队分摊区域的费用')
        {
            $totalShareAmount = 0;
            foreach ($reportData['company'] as $companyId => $data) {
                $thisCompanyProfitPercen = $percenData['companyData'][$companyId]['percen'];
                $thisCompanyShareAmount = bcmul($amount,$thisCompanyProfitPercen);
                $totalShareAmount += $thisCompanyShareAmount;
                $reportData['company'][$companyId][$cateId]['amount'] += $thisCompanyShareAmount;
            }
            $diffAmount = $amount - $totalShareAmount;
            # 差价由毛利最高的车队承担
            $maxKey = $this->_getMaxPercenKey($percenData['companyData']);
            $reportData['company'][$maxKey][$cateId]['amount'] += $diffAmount;
        }
        if($type == '计算车队分摊区域承担的费用')
        {
            # 这里是算总部费用分摊到车队的费用
            # 要先算分摊到区域的费用，并且补齐
            $totalShareAmount = 0;
            $areaShareData = [];
            foreach ($reportData['area'] as $areaId => $data) {
                $thisAreaProfitPercen = $percenData['areaData'][$areaId]['percen'];
                $thisAreaShareAmount = bcmul($amount,$thisAreaProfitPercen);
                $totalShareAmount += $thisAreaShareAmount;
                // 临时把这条数据每个区域分摊的费用存起来
                $areaShareData[$areaId] = $thisAreaShareAmount;
            }
            $diffAmount = $amount - $totalShareAmount;
            $maxKey = $this->_getMaxPercenKey($percenData['areaData']);
            $areaShareData[$maxKey] += $diffAmount;


            # 然后拿到区域的费用再去算车队分摊的费用
            $amount = $areaShareData[$reportAreaId]; // 车队分摊的费用是车队所在区域分摊的费用
            $totalShareAmount = 0;
            foreach ($reportData['company'] as $companyId => $data) {
                $thisCompanyProfitPercen = $percenData['companyData'][$companyId]['percen'];
                $thisCompanyShareAmount = bcmul($amount,$thisCompanyProfitPercen);
                $totalShareAmount += $thisCompanyShareAmount;
                $reportData['company'][$companyId][$cateId]['amount'] += $thisCompanyShareAmount;
            }
            $diffAmount = $amount - $totalShareAmount;
            # 差价由毛利最高的区域承担
            $maxKey = $this->_getMaxPercenKey($percenData['companyData']);
            $reportData['company'][$maxKey][$cateId]['amount'] += $diffAmount;
        }

        return $reportData;
        
    }

    private function _getMaxPercenKey($data)
    {
        $maxKey = null;
        $maxValue = -INF;

        foreach ($data as $key => $row) {
            if ($row['percen'] > $maxValue) {
                $maxValue = $row['percen'];
                $maxKey = $key;
            }
        }

        return ($maxKey);
    }

    /**
     * 获取公司费用分类的列表，组装成父分类、子分类的形式
     * */
    private function _getCompanyIncomeExpenseCateTreeList()
    {
        $list = db('CompanyIncomeExpenseCate')
            ->order('pid ASC, id ASC')
            ->select();

        // 按 pid 分组
        $group = [];
        foreach ($list as $v) {
            $group[$v['pid']][] = $v;
        }

        // 递归生成平面树，带缩进
        function buildFlatTree($parentId, &$group, &$result, $level = 0) {
            if (!isset($group[$parentId])) return;
            foreach ($group[$parentId] as $item) {
                // 在 title 前加上缩进符号
                $item['title'] = str_repeat('└─ ', $level) . $item['title'];
                $result[] = $item;
                buildFlatTree($item['id'], $group, $result, $level + 1);
            }
        }

        $result = [];
        buildFlatTree(0, $group, $result);

        // 输出
        return $result;
    }


    public function getCompanyIncomeExpenseList()
    {
        $page = isset($this->input_data['page']) ? $this->input_data['page'] : 1;
        $limit = isset($this->input_data['limit']) ? $this->input_data['limit'] : 15;

        $reportAreaId = $this->post('area_id') != '' ?  $this->post('area_id') : 0;
        $reportCompanyId = $this->post('company_id') != '' ?  $this->post('company_id') : 0;

        // =========================
        // # 计算提交上来的时间范围
        // =========================
        $ym        = trim($this->post('belongs_month'));
        $startDate = strtotime($ym . '-01 00:00:00');
        if ($startDate === false) $this->resErr('报表月份有误');
        $endDate   = strtotime('+1 month', $startDate);

        $map = [
            'belongs_date' => ['BETWEEN',[$startDate,$endDate]],
            'status'       => 200, // 已审核的
        ];
        $map = $this->_setCateMap($map);
        if($reportAreaId > 0) $map['area_id'] = $reportAreaId;
        if($reportCompanyId > 0) $map['company_id'] = $reportCompanyId;

        $total = 0;
        $rows = db('CompanyIncomeExpense')
            ->where(function ($q) use ($map) {
                $q->where($map)->where('belongs', '<>', '总部');
            })
            ->whereOr(function ($q) use ($startDate, $endDate) {
                $q->where('belongs_date', 'BETWEEN', [$startDate, $endDate])
                  ->where('status', 200)
                  ->where('belongs', '总部');
            })
            ->order('id', 'desc')
            ->select();

        // 查询总数和分页数据
        
        // $rows  = $query->order('id', 'desc')->page($page, $limit)->select();
        $sql = db()->getLastSql();
        $list = [];

        // 含补差价的毛利占比计算方法
        $percenData = $this->_calcProfitRatio($startDate, $endDate, $reportAreaId); 

        // 当前区域毛利占比
        $areaSharePercentage = $reportAreaId > 0 ? $percenData['areaData'][$reportAreaId]['percen'] : 0;

        // 当前车队毛利占比
        $companySharePercentage = $reportCompanyId > 0 ? $percenData['companyData'][$reportCompanyId]['percen'] : 0;
        foreach ($rows as $v) {
            // 计算本条明细区域和车队承担的金额
            $v = $this->_calcShareAmount($v,$areaSharePercentage,$companySharePercentage,$reportAreaId,$reportCompanyId);
            $v['amount'] = formatMoneyShow($v['amount']);
            $v['areaAmount'] = formatMoneyShow($v['areaAmount']);
            $v['companyAmount'] = formatMoneyShow($v['companyAmount']);
            $list[] = $v;
        }
        
        $res = [
            'total' => $total,
            'list' => $list,
            'map' => $map,
            'percenData' => $percenData,
            'sql' => $sql
        ];
        $this->resSuc($res);
    }

    // 计算一条明细里面，区域和车队承担的金额,只显示，补用不全
    private function _calcShareAmount($v,$areaSharePercentage,$companySharePercentage,$reportAreaId,$reportCompanyId)
    {
        if($reportCompanyId > 0)
        {
            // 车队报表
            if($v['belongs'] == '总部')
            {
                // 属于总部的费用，区域要按毛利比例平摊
                $v['areaAmount'] =  bcmul($v['amount'],$areaSharePercentage);
                // 车队再承担自己的
                $v['companyAmount'] =  bcmul($v['areaAmount'],$companySharePercentage);
            }
            else
            {
                // 属于自己区域的费用，区域全部承担
                $v['areaAmount'] = $v['area_id'] == $reportAreaId ?  $v['amount'] : 0;
                // 车队再承担自己的
                $v['companyAmount'] =  bcmul($v['areaAmount'],$companySharePercentage);
            }
        }
        else if($reportAreaId > 0)
        {
            // 区域报表
            if($v['belongs'] == '总部')
            {
                // 属于总部的费用，区域要按毛利比例平摊
                $v['areaAmount'] =  bcmul($v['amount'],$areaSharePercentage);
                $v['companyAmount'] = 0;
            }
            else
            {
                // 属于自己区域的费用，区域全部承担
                $v['areaAmount'] = $v['area_id'] == $reportAreaId ? $v['amount'] : 0;
                $v['companyAmount'] = 0;
            }
            
            
        }
        else
        {
            // 总报表
            $v['areaAmount'] = formatMoneyShow(0);
            $v['companyAmount'] = formatMoneyShow(0);
        }
        return $v;
    }

    /**
     * 根据传入 cate_id 判断是顶级分类还是子分类
     * 返回可直接用于 ->where($map) 的数组形式
     *
     * @param int $cateId
     * @return array
     */
    private function _setCateMap($map)
    {
        $cateId = $this->post('cate_id');
        if ($cateId > 0)
        {
            // 查询分类信息
            $cate = db('CompanyIncomeExpenseCate')->where('id', $cateId)->find();
            if (!$cate) return;

            // 顶级分类 pid=0
            if (intval($cate['pid']) === 0) {
                // 获取所有子分类ID
                $childIds = db('CompanyIncomeExpenseCate')
                    ->where('pid', $cateId)
                    ->column('id');

                // 包含顶级分类自己
                $allIds = array_merge([$cateId], $childIds);
                $map['cate_id'] = ['in', $allIds];
            } else {
                // 子分类直接返回单个 ID
                $map['cate_id'] = $cateId;
            }
        }
        return $map;
        
    }

    /**
     * 计算某个范围的毛利（收入 - 支出）
     * 
     * @param int|null $area_id  区域ID（null 表示全部区域）
     * @param string   $startDate 开始日期
     * @param string   $endDate   结束日期
     * @param int|null $company_id 车队ID（可选）
     * @return float
     */
    private function _calcProfit( $area_id, $company_id, $startDate, $endDate )
    {
        $rows = db('VehicleIncomeExpense')
            ->alias('a')->join('vehicle b','a.vehicle_id = b.id','LEFT')
            ->where('belongs_date', 'BETWEEN', [$startDate,$endDate])
            ->where('a.status',20) // 已通过已审核已付款已完成的意思
            ->where('is_void',1) // 有效
            ->select();

        $totalExpense = $areaExpense = $companyExpense = 0;
        /**
         * $totalIncome $areaIncome $companyIncome
         * 总收入、区域总收入、车队总收入。 
         * 这里指的总收入，并不是流水的总收入，而是总收费。
         * 我在出单创建收支流水的时候，把返点标记出来is_rebate = 1。这里统计“总收入”的时候，排除掉就对了。
         * 其他地方的逻辑都可以用收入减支出
         * */
        $totalIncome = $areaIncome = $companyIncome = 0;
        $totalProfit = $areaProfit = $companyProfit = 0;

        # 统计毛利
        foreach ($rows as $v) {
            $amount = $v['io_type'] === '收入' ? $v['amount'] : $v['amount'] * -1;
            $totalProfit += $amount;
            $totalIncome += $v['io_type'] === '收入' && $v['is_rebate'] == 0 ? $v['amount'] : 0; // 计算总收入
            $totalExpense += $v['io_type'] === '支出' ? $v['amount'] : 0; // 计算总支出
            if( $v['area_id'] == $area_id )
            {
                $areaProfit += $amount;
                $areaIncome += $v['io_type'] === '收入' && $v['is_rebate'] == 0 ? $v['amount'] : 0; // 计算区域总收入
                $areaExpense += $v['io_type'] === '支出' ? $v['amount'] : 0; // 计算区域总支出
            } 
            if( $v['company_id'] == $company_id ){
                $companyProfit += $amount;
                $areaIncome += $v['io_type'] === '收入' && $v['is_rebate'] == 0 ? $v['amount'] : 0; // 计算公司总收入
                $companyExpense += $v['io_type'] === '支出' ? $v['amount'] : 0; // 计算公司总支出
            } 
        }

        # 拼装返回数据
        $data = [
            'totalProfit' => $totalProfit,
            'areaProfit' => $areaProfit,
            'companyProfit' => $companyProfit,
            'totalIncome' => $totalIncome,
            'areaIncome' => $areaIncome,
            'companyIncome' => $companyIncome,
            'totalExpense' => $totalExpense,
            'areaExpense' => $areaExpense,
            'companyExpense' => $companyExpense
        ];
        return $data;
    }

    /**
     * 计算区域和车队毛利占比（整数百分比方式，保证总和100%）
     * 返回格式：
     * [
     *   'areaData' => [
     *       '区域id' => [
     *           'percen' => 占比,
     *           'totalProfit' => 总毛利,
     *           'areaProfit' => 区域毛利
     *       ],
     *   ],
     *   'companyData' => [
     *       '车队id' => [
     *           'percen' => 占比,
     *           'totalProfit' => 所在区域总毛利,
     *           'companyProfit' => 该车队毛利
     *       ]
     *   ]
     * ]
     */
    private function _calcProfitRatio($startDate, $endDate, $reportAreaId)
    {
        // 1. 获取所有区域、车队
        $areas = db('CompanyArea')->field('id')->select();
        $map = [];
        if($reportAreaId >0) $map['area_id'] = $reportAreaId;
        $companies = db('Company')->where($map)->field('id,area_id')->select();

        // 2. 拉取收支明细
        $rows = db('VehicleIncomeExpense')
            ->alias('a')
            ->join('vehicle b','a.vehicle_id = b.id','LEFT')
            ->where('belongs_date', 'BETWEEN', [$startDate, $endDate])
            ->where('a.status', 20)
            ->where('is_void', 1)
            ->field('b.area_id,b.company_id,a.io_type,a.amount')
            ->select();

        // 3. 统计区域、车队毛利
        $areaProfit = [];
        $companyProfit = [];
        $totalProfit = 0;

        foreach ($rows as $row) {
            $area_id = $row['area_id'];
            $company_id = $row['company_id'];
            $profit = $row['io_type'] === '收入' ? $row['amount'] : -$row['amount'];

            $areaProfit[$area_id] = ($areaProfit[$area_id] ?? 0) + $profit;
            $companyProfit[$company_id] = ($companyProfit[$company_id] ?? 0) + $profit;
            $totalProfit += $profit;
        }

        // 4. 初始化所有区域（即使没流水）
        foreach ($areas as $a) {
            if (!isset($areaProfit[$a['id']])) {
                $areaProfit[$a['id']] = 0;
            }
        }
        // 初始化所有车队（即使没流水）
        foreach ($companies as $c) {
            if (!isset($companyProfit[$c['id']])) {
                $companyProfit[$c['id']] = 0;
            }
        }

        // 如果全公司没有毛利
        if ($totalProfit == 0) {
            $areaData = [];
            foreach ($areas as $a) {
                $areaData[$a['id']] = [
                    'percen' => 0,
                    'totalProfit' => 0,
                    'areaProfit' => 0
                ];
            }
            $companyData = [];
            foreach ($companies as $c) {
                $companyData[$c['id']] = [
                    'percen' => 0,
                    'totalProfit' => 0,
                    'companyProfit' => 0
                ];
            }
            return ['areaData'=>$areaData,'companyData'=>$companyData];
        }

        // 5. 计算区域占比
        $areaData = [];
        $areaSumInt = 0;
        $firstNonZeroId = null;

        foreach ($areaProfit as $id => $profit) {
            $ratioInt = $totalProfit != 0 ? intval(floor(($profit / $totalProfit) * 10000)) : 0;
            $areaData[$id] = [
                'percen' => $ratioInt,
                'totalProfit' => $totalProfit,
                'areaProfit' => $profit
            ];
            $areaSumInt += $ratioInt;
            if ($firstNonZeroId === null && $profit != 0) {
                $firstNonZeroId = $id;
            }
        }

        // 补齐100%
        $diffInt = 10000 - $areaSumInt;
        if ($diffInt != 0 && $firstNonZeroId !== null) {
            $areaData[$firstNonZeroId]['percen'] += $diffInt;
        }

        // 转换为百分比（两位小数）
        foreach ($areaData as $id => $val) {
            $areaData[$id]['percen'] = $val['percen'] / 10000;
        }

        // 6. 计算车队占比（分区域）
        $companyData = [];
        // 先按区域分组车队
        $companiesByArea = [];
        foreach ($companies as $c) {
            $companiesByArea[$c['area_id']][] = $c['id'];
        }

        foreach ($companiesByArea as $area_id => $cids) {
            $areaProfitValue = $areaProfit[$area_id] ?? 0;
            if ($areaProfitValue == 0) {
                // 该区域没有毛利，全部车队占比=0
                foreach ($cids as $company_id) {
                    $companyData[$company_id] = [
                        'percen' => 0,
                        'totalProfit' => 0,
                        'companyProfit' => 0
                    ];
                }
                continue;
            }

            $companySumInt = 0;
            $firstNonZeroCompanyId = null;

            foreach ($cids as $company_id) {
                $profit = $companyProfit[$company_id] ?? 0;
                $ratioInt = intval(floor(($profit / $areaProfitValue) * 10000));
                $companyData[$company_id] = [
                    'percen' => $ratioInt,
                    'totalProfit' => $areaProfitValue,
                    'companyProfit' => $profit
                ];
                $companySumInt += $ratioInt;

                if ($firstNonZeroCompanyId === null && $profit != 0) {
                    $firstNonZeroCompanyId = $company_id;
                }
            }

            // 补齐100%
            $diffInt = 10000 - $companySumInt;
            if ($diffInt != 0 && $firstNonZeroCompanyId !== null) {
                $companyData[$firstNonZeroCompanyId]['percen'] += $diffInt;
            }
        }

        // 转换为百分比（两位小数）
        foreach ($companyData as $id => $val) {
            $companyData[$id]['percen'] = $val['percen'] / 10000;
        }

        return [
            'areaData' => $areaData,
            'companyData' => $companyData
        ];
    }




  
    public function getInsuranceReport()
    {
        // =========================
        // # 前端传入的条件
        // =========================
        $reportAreaId = $this->post('area_id') != '' ?  $this->post('area_id') : 0;

        // =========================
        // # 计算提交上来的时间范围
        // =========================
        $ym        = trim($this->post('belongs_month'));
        if( $ym == '' )
        {
            $startDate = 0;
            $endDate = time();
        }
        else
        {
            $startDate = strtotime($ym . '-01 00:00:00');
            if ($startDate === false) $this->resErr('报表月份有误');
            $endDate   = strtotime('+1 month', $startDate);
        }
        

        # 备忘：出单表judge_time 财务审核时间
        # 备忘：出单表pay_time 填写的实际付款时间
        # 备忘：出单表，200的状态是全部完成。财务刚通过发到保险部，是10的状态。
        # 备忘：保险表状态，已完成的是30

        $map = [
            'a.status' => 30,
            'trade_pay_time' => ['BETWEEN',[$startDate,$endDate]]
        ];
        if($reportAreaId > 0) $map['area_id'] = $reportAreaId; 

        # 目前按照出单的支付时间的去计算
        // 第一份
        $list1 = db('Insurance')
            ->alias('a')
            ->where($map)
            ->join('vehicle b', 'a.vehicle_id = b.id', 'LEFT')
            ->field("
                b.company,
                b.company_id,
                b.area,
                SUM(CASE WHEN a.cate = '交强险' THEN 1 ELSE 0 END) AS jqx,
                SUM(CASE WHEN a.cate = '商业险' THEN 1 ELSE 0 END) AS syx,
                SUM(CASE WHEN a.cate = '商业险' AND a.insurance = '中润统筹' THEN 1 ELSE 0 END) AS tc,
                SUM(CASE WHEN a.cate = '商业险' AND a.insurance != '中润统筹' THEN 1 ELSE 0 END) AS zg
            ")
            ->group('b.company')
            ->select();

        // 第二份
        $subQuery = db('Insurance')
            ->alias('a')
            ->where($map)
            ->join('vehicle b','a.vehicle_id = b.id','LEFT')
            ->field("
                b.company,
                b.company_id,
                b.area,
                a.vehicle_id,
                MAX(CASE WHEN a.cate='交强险' THEN 1 ELSE 0 END) AS has_jqx,
                MAX(CASE WHEN a.cate='商业险' THEN 1 ELSE 0 END) AS has_syx
            ")
            ->group('a.vehicle_id')
            ->buildSql();

        $list2 = db()->table($subQuery . ' tmp')
            ->field("
                tmp.area,
                tmp.company,
                tmp.company_id,
                SUM(CASE WHEN has_jqx=1 AND has_syx=1 THEN 1 ELSE 0 END) AS jstc
            ")
            ->group('tmp.company')
            ->select();

        // 合并
        $result = [];
        foreach ($list1 as $row) {
            $company = $row['company'];
            $result[$company] = $row;
            $result[$company]['jstc'] = 0;
        }

        foreach ($list2 as $row) {
            $company = $row['company'];
            if (isset($result[$company])) {
                $result[$company]['jstc'] = $row['jstc'];
            }
        }

        $result = array_values($result);

        $this->resSuc([
            'map' => $map,
            'list' => $result
        ]);
    }
}
















